<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>生成dop模版页面</title>
</head>
<body>
<div style="display: flex;flex-direction: column">
    <label>
        <span id="axureHTML-tip">请选择Axure导出的html文件（导出目录/页面名称.html）</span>
        <input id="axureHTML" type="file"/>
    </label>
    <label>
        <span id="axureCSS-tip">请选择Axure导出的css文件（导出目录/files/页面名称/style.css）</span>
        <input id="axureCSS" type="file"/>
    </label>
    <button id="createDopTemplateHTML">生成DOP模版页面</button>
    <p>将生成后的eletemplet.html页面覆盖原eletemplet.html。然后测试功能是否可用</p>
</div>
<script type="module">
    document.getElementById('createDopTemplateHTML').addEventListener('click',function () {
        const axureHtmlAndCssFile = getAxureHtmlAndCssFile();
        if(!axureHtmlAndCssFile.axureHTML){
            alert(document.getElementById('axureHTML-tip').innerText);
            return;
        }
        if(!axureHtmlAndCssFile.axureCSS){
            alert(document.getElementById('axureCSS-tip').innerText);
            return;
        }
        createDopTemplateHTML(axureHtmlAndCssFile);
    });
    function getAxureHtmlAndCssFile() {
        const result = {axureHTML:null,axureCSS:null};
        const axureHTML = document.getElementById('axureHTML');
        const axureCSS = document.getElementById('axureCSS');
        result.axureHTML = axureHTML && axureHTML.files[0] || null;
        result.axureCSS = axureCSS && axureCSS.files[0] || null;
        return result;
    }
    async function createDopTemplateHTML(axureHtmlAndCssFile) {
        const dopTemplate = new DopTemplate();
        await dopTemplate.setCSS(axureHtmlAndCssFile.axureCSS);
        await dopTemplate.setHTML(axureHtmlAndCssFile.axureHTML);
        dopTemplate.download();
    }



    class DopTemplate{
        htmlText = '';
        cssText = '';
        cssRules = {};
        async setHTML(file){
            const html = await this.readAsText(file);
            const matchTexts = html.match(/body>((.|\s)+)?<\/body>/);
            if(!matchTexts){
                throw new Error('未找到html文件中的body节点！');
            }
            const div = document.createElement('div');
            div.innerHTML = matchTexts[1];
            this.htmlText = this.parseElementToHtml(div);
        }
        async setCSS(file){
            this.cssText = await this.readAsText(file);
            this.cssRules = DopTemplate.getStyleSheet(this.cssText);
        }
        parseElementToHtml(ele){
            const arr = DopTemplate.getChildrenElements(ele);
            const base = arr.length === 0 ? ele : arr[0];
            DopTemplate.fixedLineBug(base);
            this.elementSwitch(base,true);
            return ele.innerHTML;
        }
        getMergedFullHTML(){
            const {htmlText,cssText} = this;
            return `<!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="UTF-8"><title>模版</title>
                    <style>p{margin: 0} .background-black{background-color: #000}</style>
                    <style>${cssText}</style>
                    </head><body>${htmlText}</body></html>`;
        }
        download(){
            const fullHTML = this.getMergedFullHTML();
            const blob = new File([new Blob([fullHTML],{type:"text/html"})],"eletemplet.html");
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = "eletemplet.html";
            a.click();
        }
        static getChildrenElements(ele){
            const children = [];
            if(!ele || ele.nodeType === 3 || ele.nodeType === 8 || !ele.childNodes || ele.childNodes.length === 0)return children;
            ele.childNodes.forEach(item=>{
                if(item && item.nodeType !== 3 && item.nodeType !== 8 ){
                    children.push(item);
                }
            });
            return children;
        }
        static fixedLineBug(ele){
            if(!ele || !ele.classList || !ele.classList.contains)return;
            if(ele.classList.contains('line')){
                ele.innerHTML = '';
                ele.classList.add('background-black');
                return;
            }
            if(ele.childNodes && ele.childNodes.length > 0){
                ele.childNodes.forEach(item=>{
                    DopTemplate.fixedLineBug(item);
                });
            }
        }
        elementSwitch(ele,root){
            if(!ele || ele.nodeType === 3 || !ele.getAttribute)return;
            const exp = ele.getAttribute("data-label");
            const showReg = /(\s|^)If(.*?)EndIf\s*/;
            const typeReg = /(\s|^)Type(.*?)EndType\s*/;
            let _exp=exp;
            let show = _exp&&_exp.match(showReg);
            show=show?show[2].trim():"";
            if(show){
                _exp=_exp.replace(showReg,"");
                show && ele.setAttribute('data-show',show);
            }
            let type = _exp&&_exp.match(typeReg);
            type=type?type[2].trim():"";
            if(type){
                _exp=_exp.replace(typeReg,"");
                type && ele.setAttribute('data-type',type);
                const id = ele.getAttribute('id');
                const rule = id && this.cssRules[id];
                if(rule){
                    ele.setAttribute('data-offset',[rule.top,rule.left,rule.width,rule.height].join(','))
                }
                if(type === 'image'){
                    ele.innerHTML = '<img src="'+_exp+'" style="width: 100%;height: 100%"/>';
                }
            }
            const textEle = ele.querySelector('.text');
            if(textEle){
                textEle.innerHTML = '';
                _exp && textEle.setAttribute('data-text',_exp);
            }
            ele.removeAttribute("data-label");
            const isGroup = root || DopTemplate.isGroup(ele);
            if(isGroup && ele.childNodes && ele.childNodes.length > 0){
                DopTemplate.getChildrenElements(ele).forEach(item=>{
                    this.elementSwitch(item);
                });
            }
        }
        static getStyleSheet(cssTxt){
            const cssRules= {};
            (cssTxt.match(/#u[a-zA-Z\d_\s]+?{(.|\s)*?}/g)||[]).forEach(item=>{
                const current = item.match(/#u([a-zA-Z\d_\s]+?){((.|\s)*?)}/);
                if(current){
                    let [txt,id,rule]=current;
                    id='u'+id.trim();
                    rule=rule.trim();
                    const rules=rule.split(";");
                    cssRules[id]={};
                    rules.forEach(_rule=>{
                        _rule=_rule.trim();
                        if(_rule){
                            const [key,value]=_rule.split(":");
                            cssRules[id][key.trim()]=value.trim();
                        }
                    })
                }
            });
            return cssRules
        }
        static isGroup(ele){
            if(!ele || !ele.parentNode)return false;
            const brother = ele.parentNode.childNodes;
            let prevNodeName='';
            for(let i=0;i<brother.length;i++){
                if(brother[i]===ele){
                    return prevNodeName === '组合' || prevNodeName === 'Group';
                }else if(brother[i].nodeName==="#comment"){
                    const data=brother[i].textContent.match(/\((.*)\)/);
                    if(data){
                        prevNodeName=data[1].replace(/\s/,"")
                    }
                }else if(brother[i].nodeName!=="#text"){
                    prevNodeName=''
                }
            }
            return prevNodeName === '组合' || prevNodeName === 'Group';
        }
        readAsText(file){
            return new Promise((resolve,reject)=>{
                const reader=new FileReader();
                reader.onerror=reject;
                reader.onload=function () {
                    resolve(this.result)
                };
                reader.readAsText(file)
            })
        }
    }
</script>
</body>
</html>